package com.leetcode;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 15. 三数之和
 * 排序 + 双指针法
 *
 * @author fy
 * @date 2022/4/7 21:26
 */
public class Solution15 {

    /**
     * 使用代码去重
     *
     * @param nums
     * @return
     */
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length < 3) {
            return res;
        }
        int n = nums.length;
        Arrays.sort(nums);

        for (int i = 0; i < n - 2; i++) {
            if (i > 0 && nums[i] == nums[i - 1]) {
                continue;
            }
            int target = -nums[i];
            int head = i + 1;
            int tail = n - 1;
            while (head < tail) {
                int sum = nums[head] + nums[tail];
                if (sum == target) {
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[head]);
                    list.add(nums[tail]);
                    res.add(list);
                    while (head + 1 < tail && nums[head] == nums[head + 1]) {
                        head++;
                    }
                    head++;
                    while (head < tail - 1 && nums[tail] == nums[tail - 1]) {
                        tail--;
                    }
                    tail--;
                } else if (sum < target) {
                    head++;
                } else {
                    tail--;
                }
            }
        }

        return res;
    }

    /**
     * 使用set去重
     *
     * @param nums
     * @return
     */
    public List<List<Integer>> threeSum1(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        if (nums == null || nums.length < 3) {
            return res;
        }
        int n = nums.length;
        Arrays.sort(nums);

        Set<List<Integer>> newRes = new HashSet<>();
        for (int i = 0; i < n - 2; i++) {
            int target = -nums[i];
            int head = i + 1;
            int tail = n - 1;
            while (head < tail) {
                int sum = nums[head] + nums[tail];
                if (sum == target) {
                    List<Integer> list = new ArrayList<>();
                    list.add(nums[i]);
                    list.add(nums[head]);
                    list.add(nums[tail]);
                    newRes.add(list);
                    head++;
                } else if (sum < target) {
                    head++;
                } else {
                    tail--;
                }
            }
        }

        return new ArrayList<>(newRes);
    }

    public static void main(String[] args) {
        int[] nums = new int[]{-1, 0, 1, 2, -1, -4};
        List<List<Integer>> res = new Solution15().threeSum(nums);
        System.out.println(res);
    }

}
